Volatility Structures¶

In [1]:
import yfinance as yf
import numpy as np
import pandas as pd
In [2]:
def download_all_call_options_data(symbol):
    ticker = yf.Ticker(symbol)
    expiration_dates = ticker.options

    all_call_options_data = pd.DataFrame()

    for exp_date in expiration_dates:
        option_chain_data = ticker.option_chain(exp_date)
        calls = option_chain_data.calls

        calls['ExpirationDate'] = exp_date
        all_call_options_data = pd.concat([all_call_options_data, calls], ignore_index=True)

    return all_call_options_data

symbol = "^SPX"
data = download_all_call_options_data(symbol)
/var/folders/yk/ss7gnth141s6qj3jlxwlyyqw0000gn/T/ipykernel_7574/507366858.py:12: FutureWarning: Behavior when concatenating bool-dtype and numeric-dtype arrays is deprecated; in a future version these will cast to object dtype (instead of coercing bools to numeric values). To retain the old behavior, explicitly cast bool-dtype arrays to numeric dtype.
  all_call_options_data = pd.concat([all_call_options_data, calls], ignore_index=True)
In [3]:
new_data1 = data[data["strike"]== 3500]
new_data2 = data[data["strike"]== 4000]
new_data3 = data[data["strike"]== 4100]
new_data1 = new_data1[new_data1["impliedVolatility"] > 0.0001]
new_data2 = new_data2[new_data2["impliedVolatility"] > 0.0001]
new_data3 = new_data3[new_data3["impliedVolatility"] > 0.0001]
In [5]:
import matplotlib.pyplot as plt
%matplotlib inline

plt.figure(figsize=(13,6), dpi=100)
plt.plot(new_data1["impliedVolatility"], label="prezzo d'esercizio 3500")
plt.plot(new_data2["impliedVolatility"], label="prezzo d'esercizio 4000")
plt.plot(new_data3["impliedVolatility"], label="prezzo d'esercizio 4100")
plt.xlabel("Tempo")
plt.ylabel("Volatilità Implicita")
plt.xticks([])
plt.legend()
plt.show()
In [8]:
yoyo[3950:4001]
Out[8]:
strike impliedVolatility ExpirationDate
3950 2750.0 0.595211 2023-12-29
3951 2800.0 0.626133 2023-12-29
3952 2850.0 0.563534 2023-12-29
3953 2900.0 0.551266 2023-12-29
3954 3000.0 0.000010 2023-12-29
3955 3075.0 0.000010 2023-12-29
3956 3100.0 0.000010 2023-12-29
3957 3125.0 0.000010 2023-12-29
3958 3200.0 0.509687 2023-12-29
3959 3225.0 0.000010 2023-12-29
3960 3250.0 0.000010 2023-12-29
3961 3275.0 0.000010 2023-12-29
3962 3300.0 0.000010 2023-12-29
3963 3325.0 0.000010 2023-12-29
3964 3350.0 0.000010 2023-12-29
3965 3375.0 0.000010 2023-12-29
3966 3400.0 0.000010 2023-12-29
3967 3425.0 0.000010 2023-12-29
3968 3450.0 0.000010 2023-12-29
3969 3475.0 0.000010 2023-12-29
3970 3500.0 0.403742 2023-12-29
3971 3525.0 0.000010 2023-12-29
3972 3550.0 0.000010 2023-12-29
3973 3560.0 0.388472 2023-12-29
3974 3570.0 0.385939 2023-12-29
3975 3575.0 0.000010 2023-12-29
3976 3590.0 0.380862 2023-12-29
3977 3600.0 0.375987 2023-12-29
3978 3610.0 0.375758 2023-12-29
3979 3620.0 0.373389 2023-12-29
3980 3625.0 0.372103 2023-12-29
3981 3630.0 0.370822 2023-12-29
3982 3640.0 0.365615 2023-12-29
3983 3650.0 0.365851 2023-12-29
3984 3660.0 0.363265 2023-12-29
3985 3675.0 0.358641 2023-12-29
3986 3680.0 0.358248 2023-12-29
3987 3690.0 0.353293 2023-12-29
3988 3700.0 0.353205 2023-12-29
3989 3710.0 0.350760 2023-12-29
3990 3720.0 0.346190 2023-12-29
3991 3725.0 0.346637 2023-12-29
3992 3730.0 0.343394 2023-12-29
3993 3740.0 0.340941 2023-12-29
3994 3750.0 0.339339 2023-12-29
3995 3760.0 0.338397 2023-12-29
3996 3770.0 0.335895 2023-12-29
3997 3775.0 0.335231 2023-12-29
3998 3780.0 0.331199 2023-12-29
3999 3790.0 0.331031 2023-12-29
4000 3800.0 0.329158 2023-12-29
In [9]:
yoyo = pd.DataFrame({'strike': data.strike, 'impliedVolatility': data.impliedVolatility, 'ExpirationDate': data.ExpirationDate})
In [13]:
# ITM ATM OTM
pd1 = yoyo[yoyo["strike"] == 4520]
pd2 = yoyo[yoyo["strike"] == 3000]
pd3 = yoyo[yoyo["strike"] == 6000]
In [14]:
save = pd1.to_excel("Volatilitystrucures10.xlsx")
save = pd2.to_excel("Volatilitystrucures11.xlsx")
save = pd3.to_excel("Volatilitystrucures12.xlsx")

DATA SAVED¶

In [1]:
import yfinance as yf
import numpy as np
import pandas as pd
In [2]:
df = pd.read_excel("IVspot.xls")
df = df[0:5]
df
Out[2]:
DATE ATM ITM OTM DAYS
0 2023-09-15 00:00:00 0.1127 1.1282 0.4941 8.0
1 2023-10-20 00:00:00 0.1375 0.6807 0.1250 33.0
2 2023-11-17 00:00:00 0.1505 0.5826 0.2012 53.0
3 2024-01-19 00:00:00 0.1738 0.5117 0.1565 94.0
4 2024-02-16 00:00:00 0.1825 0.496 0.1478 114.0
In [3]:
import matplotlib.pyplot as plt
%matplotlib inline
plt.figure(figsize=(13,6), dpi=100)
plt.plot(df.ATM, color="purple", label="ATM")
plt.plot(df.ITM, color="Orange", label="ITM")
plt.plot(df.OTM, color= "red", label="OTM")
plt.ylabel("Volatilità Implicita")
plt.xlabel("Tempo")
plt.xticks([])
plt.legend()
plt.show()
In [4]:
df = pd.read_excel("IVspotXsurface.xlsx")
df
Out[4]:
Strikeprice IV Maturity
0 4520 0.1127 8
1 4520 0.1375 33
2 4520 0.1505 53
3 4520 0.1738 94
4 4520 0.1825 114
5 3000 1.1282 8
6 3000 0.6807 33
7 3000 0.5826 53
8 3000 0.5117 94
9 3000 0.4960 114
10 6000 0.4941 8
11 6000 0.1250 33
12 6000 0.2012 53
13 6000 0.1565 94
14 6000 0.1478 114
In [5]:
import plotly.express as px

fig = px.scatter_3d(df, x='Strikeprice', y='Maturity', z='IV', color='IV', color_continuous_scale='plasma')

fig.update_layout(
    scene=dict(
        xaxis_title="Prezzo d'esercizio",
        yaxis_title="Giorni alla scadenza",
        zaxis_title="Volatilità Implicita",
    ),
    width=1000,
    height=900,
    margin=dict(l=0, r=0, b=0, t=40),  # Adjust margins if needed
    coloraxis_colorbar=dict(
        thicknessmode='pixels', thickness=20,  # Adjust the thickness
        lenmode='fraction', len=0.5,  # Adjust the length
        yanchor='bottom', y=0.3,  # Adjust the vertical position
    )
    # Add more layout customizations here
)

fig.show()
In [7]:
import plotly.graph_objects as go
import pandas as pd


fig = go.Figure(data=[
    go.Mesh3d(x=df['Strikeprice'], y=df['Maturity'], z=df['IV'], color='dodgerblue', opacity=0.70),
    go.Scatter3d(x=df['Strikeprice'], y=df['Maturity'], z=df['IV'], 
    mode='markers', marker=dict(size=7, color=df['IV'], colorscale='plasma'))
])

fig.update_layout(scene=dict(
    xaxis_title= "Prezzo d'esercizio",
    yaxis_title="Giorni alla scadenza",
    zaxis_title="Volatilità Implicita"
), width=1000, height=900)

fig.show()